import numpy as np
import pandas as pd
from sklearn import tree  #决策树
import matplotlib.pyplot as plt
from sklearn.utils import shuffle
from sklearn.neighbors import NearestNeighbors, KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB, BernoulliNB ,MultinomialNB
from sklearn import svm

def accuracy(test,predict,methodName):
    accuracy = 0.0
    for i,j in zip(test.tolist(),predict.tolist()):
        if i[0] == j:
            accuracy += 1
    accuracy = accuracy / len(test)
    print(methodName," 预测正确率 is: {0:.1f}%".format(accuracy*100))
#绘图
#绘图，显示预测和实际之间的误差
def drwa(resault,testLabelMat,title):
    plt.figure()
    plt.suptitle(title)
    plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
    plt.plot(range(len(resault)), resault,'v', label="预测值")
    plt.plot(range(len(testLabelMat)), testLabelMat,'+', label="实际值")
    plt.legend(loc="upper right")  # 显示图中的标签
    plt.xlabel("数据编号")
    plt.ylabel('结果分类')
    plt.show()

#数值化
def numerlization(Data,names):
    parents_maping = {'usual':1, 'pretentious':2, 'great_pret':3}
    has_nurs_maping = {'proper':1,'less_proper':2, 'improper':3,'critical':4,'very_crit':5}
    form_maping = {'complete':1, 'completed':2, 'incomplete':3, 'foster':4}
    housing_maping = {'convenient':1,'less_conv':2,'critical':3}
    finance_maping ={'convenient':1, 'inconv':2}
    social_maping = {'nonprob':1, 'slightly_prob':2, 'problematic':3}
    health_maping = {'recommended':1, 'priority':2, 'not_recom':3}
    Distribution_maping = {'not_recom':1,'recommend':2,'very_recom':3,'priority':4,'spec_prior':5}
    maping = [parents_maping,has_nurs_maping,form_maping,housing_maping,finance_maping,social_maping,health_maping,Distribution_maping]
    for name,map_ing in zip(names,maping):
        Data[name] = Data[name].map(map_ing)

def loadData(filename):
    Data = pd.read_csv(filename,sep=',',names=['parents','has_nurs','form','children','housing','finance','social','health','Distribution'])
    Data.dropna(axis = 0)
    row,columns = Data.shape
    Data = shuffle(Data)
    for i in  range(row):
        if Data.loc[i,'children'] == 'more':
            Data.loc[i, 'children'] = 4
    numerlization(Data,['parents','has_nurs','form','housing','finance','social','health','Distribution'])
    Data = Data.astype(np.float)
    dataSet = Data.iloc[:,0:8]
    labelSet = Data.iloc[:,8:9]
    return row,columns,dataSet,labelSet

#决策树
def myTree(dataSet,labelSet,row):
    clf = tree.DecisionTreeClassifier()
    clf = clf.fit(dataSet[200:],labelSet[200:])
    predictLabel = clf.predict(dataSet[:200])
    drwa(np.array(predictLabel),np.array(labelSet[:200]),'决策树分类效果显示')
    accuracy(np.array(labelSet[:200]), predictLabel, "决策树分类器")

#高斯朴素贝叶斯
def myGaussianNB(dataSet,labelSet,row):
    clf = GaussianNB()
    clf = clf.fit(dataSet[200:],labelSet[200:])
    predictLabel = clf.predict(dataSet[:200])
    drwa(np.array(predictLabel), np.array(labelSet[:200]), '贝叶斯分类效果显示')
    accuracy( np.array(labelSet[:200]), predictLabel, "贝叶斯分类器")

#伯努利朴素贝叶斯
def myMultinomialNB  (dataSet,labelSet,row):
    clf = MultinomialNB()
    clf = clf.fit(dataSet[200:],labelSet[200:])
    predictLabel = clf.predict(dataSet[:200])
    drwa(np.array(predictLabel), np.array(labelSet[:200]), '伯努利分类效果显示')
    accuracy( np.array(labelSet[:200]), predictLabel, "伯努利分类器")

#k近邻
def myKNeighborsClassifier(dataSet,labelSet,row):
    nbs = KNeighborsClassifier(n_neighbors=20,algorithm='auto')
    nbs.fit(dataSet[200:],labelSet[200:])
    predictLabel = nbs.predict(dataSet[:200])
    drwa(np.array(predictLabel), np.array(labelSet[:200]), 'KNN分类效果显示')
    accuracy(np.array(labelSet[:200]), predictLabel, "KNN分类器")

#支持向量机
def mySvm(dataSet,labelSet,row):
    clf = svm.SVC(decision_function_shape='ovo')
    clf.fit(dataSet[200:],labelSet[200:])
    predictLabel = clf.predict(dataSet[:200])
    drwa(np.array(predictLabel), np.array(labelSet[:200]), 'SVM多分类效果显示')
    accuracy(np.array(labelSet[:200]), predictLabel, "SVM多分类器")

if __name__ == '__main__':
    fileName = 'nursery.csv'
    row,columns,dataSet,labelSet = loadData(fileName)
    myTree(dataSet,labelSet,row)
    myGaussianNB(dataSet,labelSet,row)
    myKNeighborsClassifier(dataSet,labelSet,row)
    mySvm(dataSet,labelSet,row)

